﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using BasePlatformCommon;
using BasePlatformCommon.devChain;

namespace BasePlatformCom
{
	public class BaseCoreCom
	{
		private string version = "BaseCoreCom: v1.0.4 @ 2018.3.30";

		public bool typeLogEnable = true;							// 日志全局使能
		public bool normalLogEnable = false;						// 固定日志使能
		public bool testLogEnable = false;							// 测试日志使能
		public bool detectComLogEnable = false;						// 检测日志使能

		private static BaseCoreCom baseCoreComUnique = null;		// BaseCoreCom 单例

		public bool backgroundFlag = true;							// 标记主控检测线程是否为后台线程

		public Random random = new Random();

		private List<SerialComPort> comPortList = null;

		private List<ComMainControl> mainControlList = null;

		private List<PortInfo> portInfoList = null;

		private int baudRate = 115200;			// 串口波特率
		private int receiveTimeout = 100;		// 串口接收超时 - ms

		private int frameLength;
		private byte[] frameData = new byte[8192];
		private byte[] readBuffer = new byte[1024];

		private bool ackIsOk;
		private int readNum;
		private int waitTime;
		private int safeExitRetryTimes = 0;

		#region 基本检测变量

		public bool baseWatchRunning = false;
		private Thread baseWatchThread = null;
		private bool threadSafeExit = false;
		private int watchPeriod = 100;

		private bool lampCheckEnable = false;

		#endregion

		#region 上层命令变量

		private Queue<ComCommand> cmdQueue1;
		private Queue<ComCommand> cmdQueue2;
		private int currentCmdQueue = 1;

		private static ReaderWriterLockSlim rwLock1 = new ReaderWriterLockSlim();
		private static ReaderWriterLockSlim rwLock2 = new ReaderWriterLockSlim();

		#endregion

		// 构造函数
		private BaseCoreCom(bool normalLogEnable, bool testLogEnable, bool detectComLogEnable)
		{
			// 设置日志使能状态
			this.normalLogEnable = normalLogEnable;
			this.testLogEnable = testLogEnable;
			this.detectComLogEnable = detectComLogEnable;

			// 打印 BaseCoreNet 版本
			typeLog(version, LogFile.Normal, LogTarget.FileOnly);

			random = new Random();

			comPortList = new List<SerialComPort>();
			mainControlList = new List<ComMainControl>();
			portInfoList = new List<PortInfo>();

			cmdQueue1 = new Queue<ComCommand>();
			cmdQueue2 = new Queue<ComCommand>();
		}

		// 单例模式, 获取 BaseCoreCom 类实例
		public static BaseCoreCom getInstance(bool normalLogEnable, bool testLogEnable, bool detectLogEnable)
		{
			if (baseCoreComUnique == null)
			{
				baseCoreComUnique = new BaseCoreCom(normalLogEnable, testLogEnable, detectLogEnable);
				return baseCoreComUnique;
			}
			else
			{
				return baseCoreComUnique;
			}
		}

		// 开始基本检测
		public void startBaseWatch()
		{
			resetBaseWatchEnvironment();

			if (baseWatchRunning)
			{
				stopBaseWatch();
			}

			baseWatchThread = new Thread(baseWatchProcess);
			baseWatchThread.IsBackground = backgroundFlag;
			baseWatchThread.Start();
		}

		// 停止基本检测
		public void stopBaseWatch()
		{
			if (baseWatchRunning)
			{
				baseWatchRunning = false;
				safeExitRetryTimes = 0;
				while (threadSafeExit == false && safeExitRetryTimes < 200)	// 等待 200 * 10 = 2000ms
				{
					safeExitRetryTimes++;
					Thread.Sleep(10);
				}
			}
		}

		// 重置基本检测环境
		private void resetBaseWatchEnvironment()
		{
		}

		// 基本检测主过程 - 线程方法
		private void baseWatchProcess()
		{
			baseWatchRunning = true;
			threadSafeExit = false;

			int cycleNum = 0;
			while (baseWatchRunning)
			{
				if (lampCheckEnable == true)
				{
					Thread.Sleep(1000);
					continue;
				}

				cycleNum++;
				try
				{
					// 扫描串口, 关联主控
					scanComPort();

					// 扫描主控列表
					scanMainControl();

					// 执行上层命令队列
					executeUpLevelCommand();

					#region 打印检测结果

					//typeLog("检测周期 " + cycleNum);
					for (int k = 0; k < mainControlList.Count; k++)
					{
						ComMainControl mainCtrl = mainControlList[k];

						//typeLog("[" + mainCtrl.comPort.PortName + "]: 主控版本 " + mainCtrl.version);
						//typeLog("[" + mainCtrl.comPort.PortName + "]: 主控编号 " + mainCtrl.index);
						//typeLog("[" + mainCtrl.comPort.PortName + "]: 连接分控的数量 " + (mainCtrl.subControlInfoList_U.Count + mainCtrl.subControlInfoList_D.Count));

						for (int i = 0; i < mainCtrl.subControlInfoList_U.Count; i++)
						{
							SubControlInfo subInfo = mainCtrl.subControlInfoList_U[i];
							//typeLog("[" + mainCtrl.comPort.PortName + "] - U : subVersion = " + subInfo.version);
						}
						for (int i = 0; i < mainCtrl.subControlInfoList_D.Count; i++)
						{
							SubControlInfo subInfo = mainCtrl.subControlInfoList_D[i];
							//typeLog("[" + mainCtrl.comPort.PortName + "] - D : subVersion = " + subInfo.version);
						}

						//typeLog("[" + mainCtrl.comPort.PortName + "]: 连接附属设备的数量 " + (mainCtrl.equipmentInfoList_U.Count + mainCtrl.equipmentInfoList_D.Count));

						for (int i = 0; i < mainCtrl.equipmentInfoList_U.Count; i++)
						{
							EquipmentInfo equInfo = mainCtrl.equipmentInfoList_U[i];
							//typeLog("[" + mainCtrl.comPort.PortName + "] - U: equVersion = " + equInfo.version);
						}
						for (int i = 0; i < mainCtrl.equipmentInfoList_D.Count; i++)
						{
							EquipmentInfo equInfo = mainCtrl.equipmentInfoList_D[i];
							//typeLog("[" + mainCtrl.comPort.PortName + "] - D: equVersion = " + equInfo.version);
						}

						//typeLog("----------------------------------------");
					}

					#endregion

					Thread.Sleep(watchPeriod);
				}
				catch (Exception ex)
				{
					typeLog("Error @ detectProcess: " + ex.Message + "\n" + ex.StackTrace);
					continue;
				}
			}

			foreach (ComMainControl mainCtrl in mainControlList)
			{
				mainCtrl.stopWatch();
			}

			// 安全退出检测过程，关闭串口
			closeAllComPort();
			threadSafeExit = true;
		}

		// 扫描串口, 关联主控
		private void scanComPort()
		{
			refreshComPort();

			string[] curPortNames = SerialPort.GetPortNames();
			for (int k = 0; k < comPortList.Count; k++)
			{
				try
				{
					SerialComPort port = comPortList[k];

					bool hasDevice = hasDeviceInThisPort("com", port.PortName);

					// 当前 COM 口没有注册设备
					if (hasDevice == false)
					{
						openComPort(port);
						string index = readMainControlIndex(port);
						closeComPort(port);

						// 当前 COM 口新发现主控
						if (!index.Equals(""))
						{
							typeLog("[" + port.PortName + "]: 当前 COM 口发现主控, index = " + index);

							// 为该 COM 口注册设备
							registMainControl("com", port.PortName);
						}
						else
						{
							//typeLog("[" + port.PortName + "]: 当前 COM 口无主控");
						}
					}
					else
					{
						;
					}
				}
				catch (Exception ex)
				{
					typeLog("Error @ relateMainControl2Port: " + ex.Message + "\n" + ex.StackTrace);
					continue;
				}
			}
		}

		// 关闭所有串口
		private void closeAllComPort()
		{
			string[] curPortNames = SerialPort.GetPortNames();
			for (int k = 0; k < comPortList.Count; k++)
			{
				try
				{
					SerialComPort port = comPortList[k];
					port.Close();
				}
				catch (Exception)
				{
					continue;
				}
			}
		}

		// 查询当前端口是否已注册设备, portType - "com": 串口 / "net": 网口
		private bool hasDeviceInThisPort(string portType, string portName)
		{
			portType = portType.ToLower();
			foreach (PortInfo pInfo in portInfoList)
			{
				if (pInfo.portType.Equals(portType) && pInfo.portName.Equals(portName))
				{
					return true;
				}
			}

			return false;
		}

		// 扫描主控列表
		private void scanMainControl()
		{
			int index = 0;
			while (index < mainControlList.Count && index > -1)
			{
				if (mainControlList[index].liveFlag == false)
				{
					typeLog("Remove MainControl: " + mainControlList[index].comPort.PortName);
					unRegistMainControl("com", mainControlList[index].comPort.PortName, index);
					index--;
				}
				else
				{
					index++;
				}
			}
		}

		// 注册主控, portType - "com": 串口 / "net": 网口，启动主控检测线程
		private void registMainControl(string portType, string portName)
		{
			if (portType.ToLower().Equals("com"))
			{
				// 为 COM 口注册设备
				PortInfo portInfo = new PortInfo("com", portName, true);
				portInfoList.Add(portInfo);

				ComMainControl mainControl = new ComMainControl();
				mainControl.random = random;
				mainControl.setComPort(portName);
				mainControl.liveFlag = true;
				mainControl.startWatch(backgroundFlag);
				mainControlList.Add(mainControl);
			}
		}

		// 取消注册主控
		public void unRegistMainControl(string portType, string portName, int mainCtrlIndex)
		{
			mainControlList.RemoveAt(mainCtrlIndex);
			foreach (PortInfo info in portInfoList)
			{
				if (info.portType.Equals(portType) && info.portName.Equals(portName))
				{
					portInfoList.Remove(info);
					break;
				}
			}
		}

		#region 灯条错灯检测

		// 开启灯条错灯检测
		public void enablePortDetailDetect()
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				mainCtrl.enablePortDetailDetect();
			}
		}

		// 关闭灯条错灯检测
		public void disablePortDetailDetect()
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				mainCtrl.disablePortDetailDetect();
			}
		}

		#endregion

		#region 直接操作主控

		// 读取主控（发送卡）编号
		private string readMainControlIndex(SerialComPort port)
		{
			int regData = 0;

			ReadMainReg(port, 0x88, ref regData);

			if (ackIsOk == false)
			{
				return "";
			}
			else
			{
				return regData.ToString();
			}
		}

		// 读主控制器 Reg
		public void ReadMainReg(SerialComPort port, int regAddr, ref int regData)
		{
			frameLength = 8;

			frameData[0] = 0xAA;	// 同步低
			frameData[1] = 0x55;	// 同步高
			frameData[2] = 0x02;	// 命令
			frameData[3] = 0;		// 0
			frameData[4] = 0;		// 0
			frameData[5] = 0;		// 0
			frameData[6] = mod256(regAddr);	// 地址

			commandExec(port, 5 + 6, receiveTimeout);
			regData = readBuffer[5 + 4];
		}

		#endregion

		#region 串口通信

		// 刷新可用串口
		public void refreshComPort()
		{
			comPortList.Clear();
			string[] curPortNames = SerialPort.GetPortNames();
			foreach (String portName in curPortNames)
			{
				bool hasDevice = hasDeviceInThisPort("com", portName);
				if (hasDevice == false)
				{
					SerialComPort curPort = new SerialComPort();
					curPort.PortName = portName;
					curPort.BaudRate = baudRate;
					curPort.Parity = 0;
					curPort.ByteSize = 8;
					curPort.StopBits = 2;
					curPort.ReadTimeout = 500;
					comPortList.Add(curPort);
				}
			}
		}

		// 打开串口
		private void openComPort(SerialComPort comPort)
		{
			// 打开串口
			comPort.Open();

			// 清空接收缓冲区
			comPort.clearReceiveBuf();

			// 清空发送缓冲区
			comPort.clearSendBuf();
		}

		// 关闭串口
		private void closeComPort(SerialComPort comPort)
		{
			if (comPort.Opened)
			{
				comPort.Close();
			}
		}

		// 串口通信主过程
		public void commandExec(SerialComPort comPort, int receiveNum, int receiveTime)
		{
			// 状态复位
			ackIsOk = false;
			readNum = 0;
			waitTime = 0;

			// 计算命令校验和
			calcCheckSum();

			// 清除发送/接收缓冲
			comPort.clearSendBuf();
			comPort.clearReceiveBuf();

			// 发送命令, 接收反馈
			try
			{
				commandSend(comPort);
				readNum = commandReceive(comPort, receiveNum, receiveTime);
			}
			catch (Exception ex)
			{
				typeLog("Command Exec Error: " + ex.Message + "\n" + ex.StackTrace);
			}

			// 判断反馈状况
			if (readNum >= 5)
			{
				ackIsOk = true;
			}
		}

		// 通信数据包发送
		private void commandSend(SerialComPort comPort)
		{
			if (comPort.Opened == false)
			{
				comPort.Open();
			}

			byte[] sendData = new byte[frameLength];
			Array.Copy(frameData, sendData, frameLength);
			comPort.Write(sendData, frameLength);
		}

		// 通信数据包反馈接收
		private int commandReceive(SerialComPort comPort, int receiveNum, int receiveTime)
		{
			readNum = 0;
			waitTime = 0;

			int ackFlag = 0;
			byte[] ackData = new byte[5];
			int bytesInReceiveBuffer = 0;
			while ((ackFlag == 0 || ackFlag == 2) && (waitTime < receiveTime))
			{
				Thread.Sleep(5);
				waitTime += 5;

				// 读取数据
				bytesInReceiveBuffer = 0;
				while ((bytesInReceiveBuffer < 5) && (waitTime < receiveTime))
				{
					Thread.Sleep(5);
					waitTime += 5;
					bytesInReceiveBuffer = comPort.getBytesToRead();
				}

				if (waitTime >= receiveTime)
				{
					//typeLog("[" + curComPort.PortName + "]: Command Receive Timeout");
					return 0;
				}

				comPort.Read(ref ackData, 5);

				ackFlag = checkAck(ackData);		// 判断 ack
			}

			if (ackFlag == 1)		// 正确 ack
			{
				Array.Copy(ackData, readBuffer, ackData.Length);
				readNum += 5;
			}
			else if (ackFlag == 2)	// 错误 ack
			{
				return 0;
			}
			else if (ackFlag == 3)	// 无 ack, 直接为有效数据
			{
				Array.Copy(ackData, readBuffer, ackData.Length);
				readNum += 5;
			}

			receiveNum -= 5;
			byte[] receiveData = new byte[receiveNum];
			bytesInReceiveBuffer = 0;
			while ((bytesInReceiveBuffer < receiveNum) && (waitTime < receiveTime))
			{
				Thread.Sleep(5);
				waitTime += 5;
				bytesInReceiveBuffer = comPort.getBytesToRead();
			}
			if (waitTime >= receiveTime)
			{
				//typeLog("[" + curComPort.PortName + "]: Command Receive Timeout");
				return 0;
			}

			comPort.Read(ref receiveData, (int)receiveNum);
			Array.Copy(receiveData, 0, readBuffer, 5, receiveData.Length);
			readNum += receiveData.Length;

			return readNum;
		}

		#endregion

		#region 辅助函数

		// 打印日志
		public void typeLog(Object obj, LogFile logFile = LogFile.Normal, LogTarget logTarget = LogTarget.Both)
		{
			if (typeLogEnable == false)
			{
				return;
			}

			string str = obj.ToString();

			if (logTarget == LogTarget.CmdOnly)
			{
				Console.WriteLine(str);
			}
			else
			{
				if (logTarget == LogTarget.Both)
				{
					Console.WriteLine(str);
				}

				if (logFile == LogFile.Normal && normalLogEnable == true)
				{
					Log.NormalLogger.Info(str);
				}
				else if (logFile == LogFile.Test && testLogEnable == true)
				{
					Log.TestLogger.Info(str);
				}
				else if (logFile == LogFile.DetectNet && detectComLogEnable == true)
				{
					Log.DetectComLogger.Info(str);
				}
				else if (logFile == LogFile.Debug && detectComLogEnable == true)
				{
					Log.DebugLogger.Info(str);
				}
			}
		}

		// 计算发送校验
		public void calcCheckSum()
		{
			uint crcValue = 0;
			for (int i = 0; i < frameLength - 1; i++)
			{
				crcValue = crcValue + frameData[i];
			}
			frameData[frameLength - 1] = mod256(256 - (crcValue % 256));
		}

		// 检查 ack
		public int checkAck(byte[] ackData)
		{
			// 数据不足
			if (ackData.Length != 5)
			{
				return 0;
			}
			// 正确 ack
			else if (ackData[0] == 0xaa && ackData[1] == 0x55 && ackData[2] == 0x0a && ackData[3] == 0x01 && ackData[4] == 0xf6)
			{
				return 1;
			}
			// 错误 ack
			else if (ackData[0] == 0xaa && ackData[1] == 0x55 && ackData[2] == 0x0a && ackData[3] == 0x03 && ackData[4] == 0xf4)
			{
				return 2;
			}
			// 无 ack, 直接为有效数据
			else
			{
				return 3;
			}
		}

		// mod256
		private byte mod256(uint i)
		{
			return (byte)(0xff & (i % 256));
		}

		// mod256
		private byte mod256(int i)
		{
			return (byte)(0xff & (i % 256));
		}

		#endregion

		#region 对外功能接口

		// 获取主控连接的串口名称：mainCtrlIndex - 主控编号
		public string getMainCtrlPortName(string mainCtrlIndex)
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					return mainCtrl.comPort.PortName;
				}
			}
			
			return "";
		}

		// 获取主控活跃端口（U/D）：mainCtrlIndex - 主控编号
		public int getMainCtrlActivePort(string mainCtrlIndex)
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					return mainCtrl.getMainCtrlActivePort();
				}
			}
			
			return ComMainPort.U;
		}

		// 获取主控版本：mainCtrlIndex - 主控编号
		public string getMainCtrlVersion(string mainCtrlIndex)
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					return mainCtrl.version;
				}
			}
			
			return "";
		}

		// 获取分控版本：mainCtrlIndex - 主控编号, mainPort - 主控端口（U/D）, subDepth - 分控级联深度（从 1 开始）
		public string getSubCtrlVersion(string mainCtrlIndex, uint mainPort, int subDepth)
		{
			subDepth--;

			if (subDepth < 0)
			{
				return "";
			}

			typeLog("-----------------------------------------------", LogFile.None, LogTarget.CmdOnly);
			typeLog("mainControlList.Count = " + mainControlList.Count, LogFile.None, LogTarget.CmdOnly);

			string subVersion = "";

			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					typeLog("MainControl " + mainCtrlIndex + ": U_size = " + mainCtrl.subControlInfoList_U.Count, LogFile.None, LogTarget.CmdOnly);
					typeLog("MainControl " + mainCtrlIndex + ": D_size = " + mainCtrl.subControlInfoList_D.Count, LogFile.None, LogTarget.CmdOnly);

					if (mainPort == ComMainPort.U && subDepth < mainCtrl.subControlInfoList_U.Count)
					{
						subVersion = mainCtrl.subControlInfoList_U[subDepth].version;
					}
					else if (mainPort == ComMainPort.D && subDepth < mainCtrl.subControlInfoList_D.Count)
					{
						subVersion = mainCtrl.subControlInfoList_D[subDepth].version;
					}
					else
					{
						typeLog("subDepth " + subDepth + ": No subControl", LogFile.None, LogTarget.CmdOnly);
						subVersion = "";
					}
					break;
				}
			}

			return subVersion;
		}

		// 获取附属设备版本：mainCtrlIndex - 主控编号, mainPort - 主控端口（U/D）, equDepth - 附属设备级联深度（从 1 开始）
		public string getEquCtrlVersion(string mainCtrlIndex, uint mainPort, int equDepth)
		{
			equDepth--;

			if (equDepth < 0)
			{
				return "";
			}

			string equVersion = "";
			
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					if (mainPort == ComMainPort.U && equDepth < mainCtrl.equipmentInfoList_U.Count)
					{
						equVersion = mainCtrl.equipmentInfoList_U[equDepth].version;
					}
					else if (mainPort == ComMainPort.D && equDepth < mainCtrl.equipmentInfoList_D.Count)
					{
						equVersion = mainCtrl.equipmentInfoList_D[equDepth].version;
					}
					else
					{
						equVersion = "";
					}
					break;
				}
			}

			return equVersion;
		}

		// 获取主控挂载的分控数量：mainCtrlIndex - 主控编号
		public int getSubControlNum(string mainCtrlIndex)
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					return mainCtrl.subControlInfoList_U.Count + mainCtrl.subControlInfoList_D.Count;
				}
			}

			return 0;
		}

		// 获取主控挂载的附属设备数量：mainCtrlIndex - 主控编号
		public int getEquCtrlNum(string mainCtrlIndex)
		{
			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					return mainCtrl.equipmentInfoList_U.Count + mainCtrl.equipmentInfoList_D.Count;
				}
			}

			return 0;
		}

		// 获取分控详细信息：mainCtrlIndex - 主控编号, mainPort - 主控端口（U/D）, subDepth - 分控级联深度（从 1 开始）
		public SubControlInfo getSubCtrlInfo(string mainCtrlIndex, uint mainPort, int subDepth)
		{
			subDepth--;

			if (subDepth < 0)
			{
				return null;
			}

			foreach (ComMainControl mainCtrl in mainControlList)
			{
				if (mainCtrl.index.Equals(mainCtrlIndex))
				{
					if (mainPort == ComMainPort.U && subDepth < mainCtrl.subControlInfoList_U.Count)
					{
						return mainCtrl.subControlInfoList_U[subDepth].clone();
					}
					else if (mainPort == ComMainPort.D && subDepth < mainCtrl.subControlInfoList_D.Count)
					{
						return mainCtrl.subControlInfoList_D[subDepth].clone();
					}
					else
					{
						break;
					}
				}
			}

			return null;
		}

		/************************************************************************************************************/

		// 获取当前内核版本
		public string getVersion()
		{
			return version;
		}

		// 根据 mainControlList 的索引值获取主控编号
		public string getMainCtrlIndex(int indexInList)
		{
			if (indexInList > 0 && indexInList < mainControlList.Count)
			{
				return mainControlList[indexInList].index;
			}
			else
			{
				return "";
			}
		}

		// 获取已连接的主控数量
		public int getMainControlNum()
		{
			if (mainControlList == null)
			{
				return 0;
			}
			else
			{
				return mainControlList.Count;
			}
		}

		// 获取当前活跃的主控，默认返回列表中的第一个主控，若无主控，则返回null
		public ComMainControl getActiveComMainControl()
		{
			if (mainControlList == null || mainControlList.Count == 0)
			{
				return null;
			}
			else
			{
				return mainControlList[0];
			}
		}

		// 获取当前活跃的主控的 DVI 状态
		public int getActiveComMainControlDviStatus()
		{
			if (mainControlList == null || mainControlList.Count == 0)
			{
				return -1;
			}
			else
			{
				return int.Parse(mainControlList[0].dviStatus);
			}
		}

		// 获取串口连接设备的拓扑结构链 - 内部数据结构
		public List<ControlNode> getControlNodeList()
		{
			List<ControlNode> controlNodeList = new List<ControlNode>();

			ComMainControl activeMainControl = getActiveComMainControl();
			if (activeMainControl != null)
			{
				// 分控
				List<SubControlInfo> subControlInfoList = activeMainControl.getSubControlInfoList();
				foreach (SubControlInfo subControlInfo in subControlInfoList)
				{
					ControlNode controlNode = new ControlNode(1);
					controlNode.mySubCtrlDepth = subControlInfo.index - 1;
					controlNode.version = subControlInfo.version;
					Array.Copy(subControlInfo.replyData, controlNode.replyData, 256);
					controlNodeList.Add(controlNode);
				}

				// 附属设备
				List<EquipmentInfo> equControlInfoList = activeMainControl.getEquControlInfoList();
				foreach (EquipmentInfo equControlInfo in equControlInfoList)
				{
					ControlNode controlNode = new ControlNode(0);
					controlNode.myEquipmentDepth = equControlInfo.index - 1;
					controlNode.version = equControlInfo.version;
					//Array.Copy(equControlInfo.replyData, controlNode.replyData, 256);
					controlNodeList.Add(controlNode);
				}
			}

			return controlNodeList;
		}

		// 设置 MCU 显示参数
		public void setMcuDispParameter(int[] paras)
		{
			ComCommand cmd = new ComCommand();
			cmd.overAll = true;
			cmd.target = CommandTarget.SubCtrl;
			cmd.operType = CommandOperTpye.SetMcuDispParameter;

			cmd.paramDict = new Dictionary<string, object>();
			cmd.paramDict.Add("brightTotal", paras[0]);
			cmd.paramDict.Add("brightR", paras[1]);
			cmd.paramDict.Add("brightG", paras[2]);
			cmd.paramDict.Add("brightB", paras[3]);
			cmd.paramDict.Add("brightW", paras[4]);
			cmd.paramDict.Add("gamma", paras[5]);

			addCommand(cmd);
		}

		/************************************************************************************************************/

		// 设置灯具巡检使能
		public void setLampCheckEnable(bool enable)
		{
			lampCheckEnable = enable;
			for (int k = 0; k < mainControlList.Count; k++)
			{
				mainControlList[k].setLampCheckEnable(enable);
			}
		}

		// 获取灯具状态参数
		public LampStatePara getLampStatePara(int subIndex, int subPortIndex, int miniIndex)
		{
			ComMainControl mainControl = getActiveComMainControl();

			while (mainControl.watchThreadSleeping == false)
			{
				Thread.Sleep(1);
			}

			return mainControl.getLampStatePara(subIndex, subPortIndex, miniIndex);
		}

		#endregion

		#region 处理上层命令

		// 接收上层命令，加入命令队列
		public void addCommand(ComCommand cmd)
		{
			if (currentCmdQueue == 1)
			{
				try
				{
					rwLock1.EnterWriteLock();
					cmdQueue1.Enqueue(cmd);
				}
				finally
				{
					rwLock1.ExitWriteLock();
				}
			}
			else if (currentCmdQueue == 2)
			{
				try
				{
					rwLock2.EnterWriteLock();
					cmdQueue2.Enqueue(cmd);
				}
				finally
				{
					rwLock2.ExitWriteLock();
				}
			}
		}

		// 执行上层命令队列
		private void executeUpLevelCommand()
		{
			if (currentCmdQueue == 1)
			{
				try
				{
					rwLock2.EnterWriteLock();
					while (cmdQueue2.Count > 0)
					{
						ComCommand cmd = cmdQueue2.Dequeue();
						executeOneCommand(cmd);
					}
				}
				finally
				{
					cmdQueue2.Clear();
					currentCmdQueue = 2;
					rwLock2.ExitWriteLock();
				}
			}
			else if (currentCmdQueue == 2)
			{
				try
				{
					rwLock1.EnterWriteLock();
					while (cmdQueue1.Count > 0)
					{
						ComCommand cmd = cmdQueue1.Dequeue();
						executeOneCommand(cmd);
					}
				}
				finally
				{
					cmdQueue1.Clear();
					currentCmdQueue = 1;
					rwLock1.ExitWriteLock();
				}
			}
		}

		// 执行上层单条命令（向主控下发）
		private void executeOneCommand(ComCommand cmd)
		{
			// 全局命令
			if (cmd.overAll)
			{
				foreach (ComMainControl mainCtrl in mainControlList)
				{
					mainCtrl.addCommand(cmd);
				}
			}
			// 定点命令, 按照主控编号下发
			else
			{
				foreach (ComMainControl mainCtrl in mainControlList)
				{
					if (mainCtrl.index.Equals(cmd.hostMainCtrlId))
					{
						mainCtrl.addCommand(cmd);
					}
				}
			}
		}

		#endregion
	}

	public class PortInfo
	{
		public string portType = "";	// 端口类型：com/net

		public string portName = "";	// 网口名称

		public bool hasDevice = false;	// 是否连接设备

		public PortInfo(string portType, string portName, bool hasDevice)
		{
			this.portType = portType;

			this.portName = portName;

			this.hasDevice = hasDevice;
		}
	}
}
